# 一、定义一个学生Student类。有下面的实例属性：
# 1 姓名 name
# 2 年龄 age
# 3 成绩 score（语文，数学，英语) [每课成绩的类型为整数]
# 类方法：
#  1 获取学生的姓名：get_name() 返回类型:str
# 2 获取学生的年龄：get_age() 返回类型:int
# 3 返回3门科目中最高的分数。get_course() 返回类型:int
# 4 将每个实例学生对象写进txt文件里，要持久保存
# 举例：{"姓名":"a","年龄":29,"成绩":{"语文":99,"数学":100,"英语":85}
# 5 获取所有学生的信息
# 写好类以后，可以定义2个同学测试下:
# zm = Student('zhangming',20,[69,88,100])
class Student:
    def __init__(self, name, age, score: list):
        self.name = name
        self.age = age
        self.score = score
        with open('stu1.txt', 'r', encoding='utf-8') as f:
            all_lines = f.readlines()
        if all_lines:  # 判断文件中有没有内容，有内容，进一步判断是否存在了
            target = False  # 定义一个标记
            for line in all_lines:  # 循环每一行的内容
                if f"学生姓名：{name}" in line.strip():  # 如果说学生姓名在当前的这一行内容，去除后面的\n的化
                    target = True  # 标记变更为True
            if target:  # 如果说有内容
                pass  # 什么提示都没有
            else:  # 反之的话  就是让它可以加进去
                with open('stu1.txt', 'a', encoding='utf-8') as f:  # 使用a 追加的方式打开，写入内容
                    f.write(f"学生姓名：{name}，学生年龄：{age}，语文成绩：{score[0]}，数学成绩：{score[1]}，英语成绩：{score[2]}\n")
        else:
            with open('stu1.txt', 'a', encoding='utf-8') as f:
                f.write(f"学生姓名：{name}，学生年龄：{age}，语文成绩：{score[0]}，数学成绩：{score[1]}，英语成绩：{score[2]}\n")

    def get_name(self):
        return self.name

    def get_age(self):
        return self.age

    def get_course(self):
        r_dict = {"语文成绩": self.score[0], "数学成绩": self.score[1], '英语成绩': self.score[2]}
        # 进行排列，找到最高的成绩
        return max(r_dict, key=lambda name: r_dict[name])  # 匿名函数结合max函数，找到最高成绩


"""
if __name__ == '__main__':
    zm = Student('zhangming',20,[69,88,100])
    zs = Student('zhangsan',22,[89,12,37])
    # 调用查看姓名
    # print(zm.get_name())
    # print(zs.get_name())
    # 调用查看年龄
    # print(zm.get_age())
    # print(zs.get_age())
    # 调用最高成绩
    print(zm.get_course())
    print(zs.get_course())
"""


# 二、定义一个字典类：dictclass。完成下面的功能：
# 1 删除某个key
# 2 判断某个键是否在字典里，如果在返回键对应的值，不存在则返回"not found"
# 3 返回键组成的列表：返回类型;(list)
# 4 合并字典，并且返回合并后字典的values组成的列表。返回类型:(list)\
class Dictclass:
    def __init__(self, dict1: dict):
        self.dict1 = dict1

    def del_key(self, key):
        if key in self.dict1:
            self.dict1.pop(key)
            print(f"{key}删除成功！")
        else:
            print("删除失败！key不存在！")

    def iskey(self, key):
        if key in self.dict1:
            return "存在"
        else:
            return "not found"

    def keyList(self):
        return list(self.dict1.keys())

    def updateDict(self, dict2):
        self.dict1.update(dict2)
        return list(self.dict1.values())


"""
if __name__ == '__main__':
    # 创建对象
    d1 = Dictclass({"name":"suki",'address':'辽宁','phone':'1686722'})
    # 删除key
    d1.del_key('name')
    # 判断是否存在
    print(d1.iskey('phone'))
    # 返回key列表
    print(d1.keyList())
    # 更新字典，返回的是合并字典后的value值
    print(d1.updateDict({"sex": "女"}))
"""


# 三、定义一个列表的操作类：Listinfo
# 包括的方法:
# 1 列表元素添加: add_key(keyname) [keyname:字符串或者整数类型]
# 2 列表元素取值：get_key(num) [num:整数类型]
# 3 列表合并：update_list(list) [list:列表类型]
# 4 删除并且返回最后一个元素：del_key()
class Listinfo:
    def __init__(self, list_obj: list):
        self.list_obj = list_obj

    def add_key(self, keyname):
        if isinstance(keyname, str):
            self.list_obj.append(keyname)
        elif isinstance(keyname, int):
            self.list_obj.append(keyname)
        else:
            print("添加失败！类型不是整数或者字符串")

    def get_key(self, num: int):
        if num <= len(self.list_obj):  # [10,20,30,40] ，num = 4
            return self.list_obj[num - 1]
        else:
            raise "index error，索引越界了"

    def update_list(self, list1):
        self.list_obj.extend(list1)

    def del_key(self):
        return self.list_obj.pop(len(self.list_obj) - 1)  # 使用索引的方式，用pop删除最后一个元素的内容，并返回


"""
if __name__ == '__main__':
    # 通过Listinfo类创建l1对象
    l1 = Listinfo([11,22,33])
    # 使用添加key方法
    l1.add_key(100)
    # 使用获取key方法
    print(l1.get_key(3))
    # 使用更新列表方法
    l1.update_list([100,200,300])
    # 使用删除key方法
    print(l1.del_key())
"""


# 四、做一个学生点名系统，系统里支持：存入学生、更改学生、删除学生、点到学生姓名方法
# 存入学生（姓名、年龄、家庭地址、手机号）： 存入成功后，提示xxx存入成功
# 更改学生（姓名、年龄、家庭地址、手机号）：可以修改学生内容的任意一个字段
# 删除学生：删除的学生将不在展示
# 展示全部学生：可以看到全部的学生姓名
# 学生姓名：随机抽取任意一个存在的学生信息，然后打印：到！。举例： 刘闯到！
class StuSystem:
    def insertStu(self, name, age, address, phone):
        # 也是一样，先去查看，看有没有重复的，米有重复可以添加
        with open('stuSystem2.txt', 'r', encoding='utf-8') as f:
            all_lines = f.readlines()
        if all_lines:
            target = False
            for line in all_lines:
                if f"姓名：{name}" in line.strip():
                    target = True
            if target:  # 如果说这个target变成了True，就说明已经有这个学生姓名，有的话就别加了
                print(f"您要添加的：{name}已经存在了，添加失败！")
            else:  # 如果说这个target还是False，就说明这个值不存在的，就可以正常使用追加的方式加入进去
                with open('stuSystem2.txt', 'a', encoding='utf-8') as f:
                    f.write(f"姓名：{name}，年龄：{age}，地址：{address}，手机号码：{phone}\n")
                print("添加成功！")

        else:  # 反之，就说明它是一个空文件，空文件就不判断了，直接写入，因为不可能会重复的
            with open('stuSystem2.txt', 'a', encoding='utf-8') as f:
                f.write(f"姓名：{name}，年龄：{age}，地址：{address}，手机号码：{phone}\n")
            print("添加成功！")

    def updateStu(self, oldname, newName, age, address, phone):
        with open('stuSystem2.txt', 'r', encoding='utf-8') as f:
            all_lines = f.readlines()
        if all_lines:
            r_result = []  # 定义列表，后续要写入的
            target = False
            for line in all_lines:
                if f"姓名：{oldname}" in line.strip():
                    target = True
                    continue
                r_result.append(line)
            if target:  # 如果说这个target变成了True，就说明已经有这个学生姓名，有的话就可以修改
                # 先把要修改的内容进行整理
                r_result.append(f"姓名：{newName}，年龄：{age}，地址：{address}，手机号码：{phone}\n")

                with open('stuSystem2.txt', 'w', encoding='utf-8') as f:
                    f.writelines(r_result)
                print("修改成功过！")
            else:  # 如果说这个target还是False，就说明这个值不存在的，不能修改
                print("修改失败！这个学生姓名是不存在的")
        pass

    def deleteStu(self, name):
        with open('stuSystem2.txt', 'r', encoding='utf-8') as f:
            all_lines = f.readlines()
        if all_lines:
            target = False
            for line in all_lines:
                if f"姓名：{name}" in line.strip():
                    all_lines.remove(line)
                    target = True
            if target:
                with open('stuSystem2.txt','w',encoding='utf-8') as f:
                    f.writelines(all_lines)     # 用覆盖写入的方式  将删除掉的内容写进去

                print(f"{name}删除成功!")
            else:
                print(f"删除失败")
        else:
            print("当前学生系统是空的，您要删除的学生不存在！")

    def showAll(self):
        # 展示全部学生：可以看到全部的学生姓名
        with open('stuSystem2.txt', 'r', encoding='utf-8') as f:
            all_lines = f.readlines()
        for line , value in enumerate(all_lines):
            print(f"当前第{line+1}行的信息是：{value.strip()}")

    def choceStu(self):
        from random import choice
        with open('stuSystem2.txt', 'r', encoding='utf-8') as f:
            all_lines = f.readlines()
        line = choice(all_lines)
        line = line.strip().split('，')[0]      # ['姓名：{newName}']
        name = line.split('：')[1]     # ['姓名','xxx']
        print(f"{name}到！")

"""
if __name__ == '__main__':
    # 通过StuSystem创建s1对象
    s1 = StuSystem()
    # 调用insertStu插入学生方法
    s1.insertStu('张三',19,'辽宁','17868672')
    s1.insertStu('张1',21,'辽宁','1786867221')
    # 调用updateStu 更改学生方法
    # s1.updateStu('张三','张立国',29,'辽宁沈阳','168675722')
    # 调用deleteStu 删除学生方法
    # s1.deleteStu('张立国')
    # 调用showAll方法展示学生信息
    # s1.showAll()
    # 调用随机点名
    s1.choceStu()
"""








# 五、点餐管理系统
# 1》、餐馆可以新增菜品、下架菜品、修改菜品
# 2》、每个菜品，都有对应的库存，所有菜品的库存均为999，每出一道菜，库存-1
# 菜品有对应的价格，餐厅老板定义价格每道菜不允许超过15元，没有小数单位，均为整数
# 3》、餐馆后台有点赞系统，能够收集客户对菜品的喜好，0~5分
# 4》、有菜品评分提报功能，对平均分数（菜品总分/打分人数）低于3分的菜品进行强制下架；




# 六、定义一个桌子类（Desk），包含长（length）、宽（width）、高（height）属性，
# 包含一个打印桌子信息属性的方法（showInfo）。实例化2个桌子对象，为其赋予不同的属性值，
# 并调用showInfo方法，输出每个桌子的信息。
class Desk:
    def __init__(self,length,width,height):
        self.length = length
        self.width = width
        self.height = height

    def shoInfo(self):
        print(f"桌子长：{self.length}，宽：{self.width}，高：{self.height}")
"""
if __name__ == '__main__':
    # 实例化对象
    d1 = Desk(10,20,30)
    d2 = Desk(11,21,31)
    # 展示详细信息
    d1.shoInfo()
    d2.shoInfo()
"""

# 七、定义一个用户类(User),用户名(username)和密码(password)是这个类的属性。
class User:# 七、定义一个用户类(User),用户名(username)和密码(password)是这个类的属性。
    def __init__(self,username,password):
        self.username= username
        self.password = password


# 八、定义一个计算器类，有加减乘除四个方法
class Jisuan:
    def __init__(self,a,b):
        self.a = a
        self.b = b
    def yunsuan(self,fu):
        if fu == '*':
            return self.a*self.b
        elif fu =='/':
            return self.a/self.b
        elif fu == '-':
            return self.a - self.b
        elif fu == "+":
            return self.a+self.b

# 九、创建一个名为Person的类，具有以下属性和方法：
# 属性：name（姓名），age（年龄）
# 方法：greet()，打印出一句问候语，包括该人的姓名和年龄
class Person:
    def __init__(self,name,age):
        self.name = name

        self.age = age
    def greet(self):
        print("say hello！我是：%s，今年：%s岁"%(self.name,self.age))

# 十、定义一个图书管理系统类，图书可以新增、修改、删除，要求新增的每个图书都加到txt文本里，数据持久化
# 新增：图书名、作者名称、新建年月日
# 修改：图书名、作者名称、新建年月日
# 删除：图书删掉，且不在展示
# 查看：全量查询，精确查询，需要用户传入形参来控制返回结果



# 十一、创建一个名为"Car"的类，该类具有"品牌"和"颜色"属性。
# 创建一个"start_engine"方法，该方法打印出"启动汽车引擎！"的消息。
# 创建一个"stop_engine"方法，该方法打印出"关闭汽车引擎！"的消息
class Car:
    def __init__(self,branch,color):
        self.branch = branch
        self.color = color
    def start_engine(self):
        print("启动汽车引擎！")
    def stop_engine(self):
        print("关闭汽车引擎！")
# 十二、淘宝商家后台，可以上架商品、下架商品，功能如下：
#  （1） 可以添加商品，商家添加完的商品会存到商品列表
#  1.1  商品要有名称、sku、价格
#  （2） 可以修改商品信息：名称、sku、价格
#  （3） 可以对商品进行下架，下架后的商品不再展示


# 十三、定义一个人类
# 1.小明和小美都爱跑步
# 2.小美体重45.0公斤
# 3.小明体重75.0公斤
# 4.每次跑步都会减少0.5公斤
# 5.每次吃东西都会增加1公斤
class Person1:
    def __init__(self,tizhong:int):
        self.tizhong = tizhong
    def run(self):
        self.tizhong -= 0.5
    def eat(self):
        self.tizhong +=1


# 十四、士兵瑞恩有一把ak47
# 士兵可以开火（开火扣动的是扳机）
# 枪能够发射子弹（把子弹打出去）
# 抢能够装子弹–增加子弹数量
# 要求没子弹，需要输出没有子弹了，且发射失败
# 十五、在Linux中部署Mysql，确保远程连接可以访问
# 远程数据库连接需要检查的几个事：
# 【1】 阿里云后台的3306端口有没有开放（实例—安全组规则—配置规则—3306）
# 【2】宝塔有没有放行3306端口  （安全组规则—添加端口-3306）
# 【3】看自己的有没有授权远程账号
# use mysql      进入mysql数据库
#
# grant all privileges on *.* to 'root'@'%' identified by '1965331442Xby@';
# 新建一个具有远程访问权限的用户，用户名为root，密码为1965331442Xby@
#
# flush privileges;
# 并刷新加载权限
#
# 退出mysql                                ctrl+z
# 在外面去执行：service mysqld restart
